/*
 * Copyright (C) 2020 The LINN Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.juqimiao.linn.extension;

import com.juqimiao.linn.context.BusinessPoint;
import lombok.Data;

/**
 * 扩展协助类，记录定位一个扩展的信息。
 * 其中，businessPointUniqueIdentity和extensionPointName用来识别一个特定且唯一的
 * 继承与{@link ExtensionPointI}的特定接口的Extension实现。
 * e.g:
 * 如定义一个 NewCustomerValidateExtPoint extends ExtensionPointI
 * 特定Extension类可能定义为：NewCustomerValidateExt implements NewCustomerValidateExtPoint.
 *
 * @author  Collin Cai
 * @date    2020/2/3
 */

@Data
public class ExtensionCoordinator {
    /* ---- Fields ---------- */

    private String extensionPointName;
    private String businessPointUniqueIdentity;
    private Class extensionPointClass;
    private BusinessPoint businessPoint;

    /* ---- Constructor ---------- */

    /**
     * 实例化一个{@link ExtensionCoordinator}。
     *
     * @param extPtClass    继承自{@link ExtensionPointI}的特定接口{@link Class}。
     * @param businessPoint {@link BusinessPoint}。
     */
    public ExtensionCoordinator(Class extPtClass, BusinessPoint businessPoint) {
        this.extensionPointClass = extPtClass;
        this.extensionPointName = extPtClass.getName();
        //由以下两个元素识别一个唯一的业务扩展点。
        this.businessPoint = businessPoint;
        this.businessPointUniqueIdentity = businessPoint.getUniqueId();
    }

    /**
     * 实例化一个{@link ExtensionCoordinator}。
     *
     * @param extensionPoint 表示继承与{@link ExtensionPointI}的特定接口{@link Class}的全名称。
     * @param businessPoint  一个业务扩展点的字符串表示。
     */
    public ExtensionCoordinator(String extensionPoint, String businessPoint) {
        this.extensionPointName = extensionPoint;
        this.businessPointUniqueIdentity = businessPoint;
    }

    /* ---- Overridden Methods, hashCode/equals/toString ---------- */

    /**
     * 重写的hashCode方法。
     *
     * @return 返回一个hash值。
     */
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + ((businessPointUniqueIdentity == null) ? 0 : businessPointUniqueIdentity.hashCode());
        result = 31 * result + ((extensionPointName == null) ? 0 : extensionPointName.hashCode());
        return result;
    }

    /**
     * 重写的equals方法。
     *
     * @param obj 用于比较的当前类型的相同类型实例。
     * @return 返回表示是否相等的布尔类型，True: 表示相等，False：表示不相等。
     */
    @Override
    public boolean equals(Object obj) {

        //地址相等
        if (this == obj) {
            return true;
        }
        //非空性：对于任意非空引用x，x.equals(null)应该返回false。
        if (obj == null) {
            return false;
        }

        /** Todo: 需要思考是否需要。 */
        if (this.getClass() != obj.getClass()) {
            return false;
        }

        /** Todo： Review it again. */
        ExtensionCoordinator other = (ExtensionCoordinator) obj;
        if (businessPointUniqueIdentity == null) {
            if (other.businessPointUniqueIdentity != null) {
                return false;
            }
        } else if (!businessPointUniqueIdentity.equals(other.businessPointUniqueIdentity)) {
            return false;
        }
        if (extensionPointName == null) {
            if (other.extensionPointName != null) {
                return false;
            }
        } else if (!extensionPointName.equals(other.extensionPointName)) {
            return false;
        }
        return true;
    }

    /**
     * 重写的toString方法。
     *
     * @return 返回字符串表示。
     */
    @Override
    public String toString() {
        String result = String.format("ExtensionCoordinator { extensionPointName:%s, businessPointUniqueIdentity:%s }",
                extensionPointName,
                businessPointUniqueIdentity);
        return result;
    }

    /* ---- Static method ---------- */

    /**
     * 获取一个{@link ExtensionCoordinator}实例。
     * @param extPtClass 继承自{@link ExtensionPointI}的特定接口{@link Class}。
     * @param businessPoint 一个业务扩展点的字符串表示。
     * @return 返回{@link ExtensionCoordinator}实例。
     */
    public static ExtensionCoordinator getInstance(Class extPtClass, BusinessPoint businessPoint) {
        return new ExtensionCoordinator(extPtClass, businessPoint);
    }
}
